/*
 * Zed Attack Proxy (ZAP) and its related class files.
 *
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 *
 * Copyright the ZAP Development team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Please note that this file was originally released under the 
 * GNU General Public License  as published by the Free Software Foundation; 
 * either version 2 of the License, or (at your option) any later version
 * by Compass Security AG
 * 
 * As of October 2014 Compass Security AG granted the OWASP ZAP Project 
 * permission to redistribute this code under the Apache License, Version 2.0 
 */

package ch.csnc.extension.ui;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.LayoutStyle;
import javax.swing.SwingConstants;
import javax.swing.filechooser.FileFilter;

import org.parosproxy.paros.Constant;
import org.parosproxy.paros.model.Model;
import org.parosproxy.paros.view.AbstractFrame;
import org.zaproxy.zap.utils.ZapTextField;

import ch.csnc.extension.util.DriverConfiguration;

public class DriversView extends AbstractFrame {

	private static final long serialVersionUID = -7502331281272992501L;

	private DriverTableModel driverTableModel;
	private JTable driverTable;

	private JButton addButton;
	private JButton browseButton;
	private JButton closeButton;
	private JButton deleteButton;

	private JScrollPane driverScrollPane;

	private JLabel fileLabel;
	private ZapTextField fileTextField;

	private JLabel nameLabel;
	private ZapTextField nameTextField;

	private JLabel slotLabel;
	private ZapTextField slotTextField;

	private JLabel slotListIndexLabel;
	private ZapTextField slotListIndexTextField;


	/**
	 * Creates new form Drivers
	 *
	 * @param driverConfig
	 */
	public DriversView(DriverConfiguration driverConfig) {
		this.driverTableModel = new DriverTableModel(driverConfig);
		initComponents();
		setVisible(true);
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	private void initComponents() {
		fileLabel = new JLabel();
		fileTextField = new ZapTextField();
		browseButton = new JButton();
		nameLabel = new JLabel();
		nameTextField = new ZapTextField();
		slotLabel = new JLabel();
		slotTextField = new ZapTextField();
		slotListIndexLabel = new JLabel();
		slotListIndexTextField = new ZapTextField();
		addButton = new JButton();
		deleteButton = new JButton();
		closeButton = new JButton();
		driverScrollPane = new JScrollPane();
		driverTable = new JTable();

		setTitle(Constant.messages.getString("certificates.pkcs11.drivers.title"));
		fileLabel.setText(Constant.messages.getString("certificates.pkcs11.drivers.label.path"));

		browseButton.setText(Constant.messages.getString("certificates.pkcs11.drivers.button.browse"));
		browseButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				browseButtonActionPerformed(evt);
			}
		});

		nameLabel.setText(Constant.messages.getString("certificates.pkcs11.drivers.label.name"));

		slotLabel.setText(Constant.messages.getString("certificates.pkcs11.drivers.label.slot"));

		slotListIndexLabel.setText(Constant.messages.getString("certificates.pkcs11.drivers.label.slotIndex"));

		addButton.setText(Constant.messages.getString("certificates.pkcs11.drivers.button.add"));
		addButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				addButtonActionPerformed(evt);
			}
		});

		deleteButton.setText(Constant.messages.getString("certificates.pkcs11.drivers.button.delete"));
		deleteButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				deleteButtonActionPerformed(evt);
			}
		});

		closeButton.setText(Constant.messages.getString("certificates.pkcs11.drivers.button.close"));
		closeButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				closeButtonActionPerformed(evt);
			}
		});

		driverTable.setModel(driverTableModel);
		driverScrollPane.setViewportView(driverTable);

		// When experimental SlotListIndex support is used, the slotTextField is disabled (and vice versa),
		// as only one of these parameters is actually used.
		if (!Model.getSingleton().getOptionsParam().getExperimentalFeaturesParam().isExerimentalSliSupportEnabled()) {
			slotTextField.setEnabled(false);
		}
		
		
		final GroupLayout layout = new GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING)
												.addComponent(fileLabel)
												.addComponent(nameLabel)
												.addComponent(slotLabel)
												.addComponent(slotListIndexLabel)
												.addGroup(
														layout.createSequentialGroup()
																.addGroup(
																		layout.createParallelGroup(
																				GroupLayout.Alignment.TRAILING,
																				false)
																				.addComponent(
																						nameTextField,
																						GroupLayout.Alignment.LEADING)
																				.addComponent(
																						slotTextField,
																						GroupLayout.Alignment.LEADING)
																				.addComponent(
																						slotListIndexTextField,
																						GroupLayout.Alignment.LEADING)
																				.addComponent(
																						fileTextField,
																						GroupLayout.Alignment.LEADING,
																						GroupLayout.DEFAULT_SIZE,
																						322,
																						Short.MAX_VALUE))

																.addPreferredGap(
																		LayoutStyle.ComponentPlacement.RELATED)
																.addGroup(
																		layout.createParallelGroup(
																				GroupLayout.Alignment.LEADING)
																				.addComponent(
																						addButton,
																						GroupLayout.DEFAULT_SIZE,
																						80,
																						Short.MAX_VALUE)
																				.addComponent(
																						browseButton))))
								.addContainerGap(165, Short.MAX_VALUE))
				.addGroup(
						GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addGap(499, 499, 499)
								.addComponent(closeButton,
										GroupLayout.DEFAULT_SIZE, 74,
										Short.MAX_VALUE).addContainerGap())
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(driverScrollPane,
										GroupLayout.DEFAULT_SIZE, 561,
										Short.MAX_VALUE).addContainerGap())
				.addGroup(
						GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addContainerGap(499, Short.MAX_VALUE)
								.addComponent(deleteButton).addContainerGap()));
		layout.setVerticalGroup(layout
				.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(
						GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addContainerGap()

								.addComponent(fileLabel)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.LEADING,
												false)
												.addComponent(browseButton, 0,
														0, Short.MAX_VALUE)
												.addComponent(fileTextField))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)

								.addComponent(nameLabel)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(
														nameTextField,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE))
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)

								.addComponent(slotLabel)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(
														slotTextField,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE))
								.addGap(28, 28, 28)

								.addComponent(slotListIndexLabel)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
												.addComponent(
														slotListIndexTextField,
														GroupLayout.PREFERRED_SIZE,
														GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE)
												.addComponent(
														addButton,
														GroupLayout.PREFERRED_SIZE,
														19,
														GroupLayout.PREFERRED_SIZE))
								.addGap(28, 28, 28)

								.addComponent(driverScrollPane,
										GroupLayout.PREFERRED_SIZE, 195,
										GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(deleteButton)
								.addPreferredGap(
										LayoutStyle.ComponentPlacement.RELATED,
										9, Short.MAX_VALUE)
								.addComponent(closeButton,
										GroupLayout.PREFERRED_SIZE, 10,
										GroupLayout.PREFERRED_SIZE)
								.addContainerGap()));

		layout.linkSize(SwingConstants.VERTICAL, new Component[] { addButton,
				browseButton, closeButton, deleteButton, fileTextField,
				nameTextField });

		for (int i=0; i<driverTableModel.getColumnCount(); i++) {
			driverTable.getColumnModel().getColumn(i).setPreferredWidth(driverTableModel.getPreferredWith(i));
		}

		pack();
	}

	private void browseButtonActionPerformed(ActionEvent evt) {
		final JFileChooser fc = new JFileChooser();
		fc.setFileFilter(new FileFilter() {
			@Override
			public String getDescription() {
				return "DLL/dylib";
			}

			//FIXME: Support so and dynlib files as well

			@Override
			public boolean accept(java.io.File f) {
				return f.isDirectory() || f.getName().toLowerCase().endsWith(".dll") || f.getName().toLowerCase().endsWith(".dylib");
			}
		});

		final int state = fc.showOpenDialog(null);

		if (state == JFileChooser.APPROVE_OPTION) {
			fileTextField.setText(fc.getSelectedFile().toString());
		}
	}

	private void addButtonActionPerformed(ActionEvent evt) {
		final String name = nameTextField.getText();
		final String file = fileTextField.getText();
		int slot = -1;
		int slotListindex = -1;
		try {
			slot = Integer.parseInt(slotTextField.getText());
		} catch (final Exception e) {
			slotTextField.setText("0");
		}
		try {
			slotListindex = Integer.parseInt(slotListIndexTextField.getText());
		} catch (final Exception e) {
			slotListIndexTextField.setText("0");
		}

		if (name != null && name.trim().length() > 0
						&& file != null
						&& file.trim().length() > 0
						&& slot > -1 && slotListindex > -1) {
			driverTableModel.addDriver(
					name,
					file,
					slot,
					slotListindex);

			nameTextField.setText("");
			fileTextField.setText("");
			slotTextField.setText("0");
			slotListIndexTextField.setText("0");
		}
	}

	private void deleteButtonActionPerformed(ActionEvent evt) {
		final int selrow = driverTable.getSelectedRow();
		if (selrow > -1) {
			driverTableModel.deleteDriver(selrow);

			nameTextField.setText("");
			fileTextField.setText("");
			slotTextField.setText("0");
			slotListIndexTextField.setText("0");
		}
	}

	private void closeButtonActionPerformed(ActionEvent evt) {
		setVisible(false);
		dispose();
	}

}
